package com.zhhtech.zhh.ui.widget

import android.app.Activity
import android.content.Context
import android.net.Uri
import android.os.Build
import android.util.AttributeSet
import android.webkit.*
import android.webkit.WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.LifecycleOwner
import com.zhhtech.zhh.ui.R
import com.zhhtech.zhh.ui.dialog.showAlertDialog
import com.zhhtech.zhh.ui.ext.DefaultLifecycleObserver
import com.zhhtech.zhh.ui.ext.getString
import com.zhhtech.zhh.ui.tool.image.select.imageSelect
import com.zhhtech.zhh.ui.tool.image.select.service.IImageSelect
import com.zhhtech.zhh.ui.utils.Logger
import me.jessyan.autosize.AutoSize


typealias TitleChangeListener = (title: String) -> Unit

open class X5WebView : WebView, DefaultLifecycleObserver {
    private val injectedObjectMap: HashMap<String, com.zhhtech.zhh.ui.widget.jsbridge.BaseInjected> = HashMap()
    var titleChangeListener: TitleChangeListener? = null
    private val mImageSelect: IImageSelect? by lazy {
        (context as? FragmentActivity)?.imageSelect
    }
    private var mFilePathCallback: ValueCallback<Array<Uri>>? = null

    constructor(context: Context) : this(context, null)

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
        if (!isInEditMode) {
            init(attrs)
        }
    }

    private fun init(attrs: AttributeSet?) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            setWebContentsDebuggingEnabled(true)
        }
        settings.apply {
            javaScriptEnabled = true
            domStorageEnabled = true
            cacheMode = WebSettings.LOAD_NO_CACHE
            setAppCacheMaxSize(1024 * 1024 * 8.toLong())
            setAppCachePath(context.cacheDir.absolutePath)
            allowFileAccess = true
            setAppCacheEnabled(true)
            userAgentString += "__APP"
            setSupportZoom(true)
            mixedContentMode = MIXED_CONTENT_ALWAYS_ALLOW
        }
        webViewClient = object : WebViewClient() {
            override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
                view.loadUrl(url)
                return true
            }

            override fun onPageFinished(webView: WebView, url: String?) {
                titleChangeListener?.invoke(webView.title ?: R.string.app_name.getString())
            }
        }
        webChromeClient = object : WebChromeClient() {
            override fun onJsAlert(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {
                (context as? Activity)?.apply {
                    showAlertDialog {
                        message(message = message ?: "")
                        positiveButton { result?.confirm() }
                    }
                }
                return true
            }

            override fun onJsPrompt(
                view: WebView?,
                url: String?,
                message: String?,
                defaultValue: String?,
                result: JsPromptResult?,
            ): Boolean {
                com.zhhtech.zhh.ui.widget.jsbridge.InjectedUtils.handH5(injectedObjectMap, view, url, message, defaultValue, result)
                return true
            }

            override fun onShowFileChooser(
                webView: WebView?,
                filePathCallback: ValueCallback<Array<Uri>>?,
                fileChooserParams: FileChooserParams?,
            ): Boolean {
                Logger.e("test", "openFileChooser 4:$filePathCallback")
                mFilePathCallback = filePathCallback
                selectImage()
                return true
            }
        }
    }

    private fun selectImage() {
        Logger.e("selectImage")
        mImageSelect?.selectImage {
            isMultipleChoice = false
            onCancelSuccessListener = { mFilePathCallback?.onReceiveValue(null) }
            onUploadSuccessListener = {
                if (it.isNullOrEmpty()) {
                    onCancelSuccessListener?.invoke()
                } else {
                    mFilePathCallback?.onReceiveValue(it.map { Uri.parse(it.path) }.toTypedArray())
                }
            }
        }
    }

    fun putInjected(key: String, injected: com.zhhtech.zhh.ui.widget.jsbridge.BaseInjected) {
        injectedObjectMap[key] = injected
    }

    fun bindLifecycleOwner(owner: LifecycleOwner) {
        owner.lifecycle.addObserver(this)
    }

    override fun onDestroy(owner: LifecycleOwner) {
        owner.lifecycle.removeObserver(this)
        destroy()
    }

    override fun setOverScrollMode(mode: Int) {
        super.setOverScrollMode(mode)
        (context as? Activity)?.also(AutoSize::autoConvertDensityOfGlobal)
    }

    override fun destroy() {
        super.destroy()
        for ((_, value) in injectedObjectMap) {
            value.onDestroy()
        }
        injectedObjectMap.clear()
    }
}